package dev.ece.util.io;

import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
 * 读取
 * @author DEVILIVED
 *
 */
public class LittleEndianInputStream extends FilterInputStream {

	private int size;
	
	public LittleEndianInputStream(InputStream is) throws IOException {
		super(is);
		this.size = is.available();
	}
	
	public int position() throws IOException {
		return size - this.available();
	}

	public int readInt() throws IOException {
		byte[] buff = new byte[4];
		readFully(buff, 0, 4);
		return (buff[3] << 24) 
			+ ((buff[2] << 24) >>> 8) 
			+ ((buff[1] << 24) >>> 16) 
			+ ((buff[0] << 24) >>> 24);
	}
	
	public long readUnsignedInt() throws IOException{
		byte[] buff = new byte[4];
		readFully(buff, 0, 4);
	    return ((buff[0] & 0xFF) << 24)
	                + ((buff[1] & 0xFF) << 16)
	                + ((buff[2] & 0xFF) << 8)
	                + (buff[3] & 0xFF);
	}
	
	public int readUnsignedShort() 
		throws IOException {
		byte[] buff = new byte[2];
		readFully(buff, 0, 2);
		return ((buff[1] << 24) >>> 16) 
				+ ((buff[0] << 24) >>> 24);
	}
	
	public short readShort() 
		throws IOException {
		byte[] buff = new byte[2];
		readFully(buff, 0, 2);
		return (short)((buff[1] << 8) 
				+ ((buff[0] << 24) >>> 24));
	}

	public byte readByte() throws IOException {
		return (byte) this.read();
	}
	
	public int readUnsignedByte() throws IOException {
		return this.read() & 0xFF;
	}
	
	public char readUnsignedChar()
		throws IOException {
		return (char) ((this.readByte() << 24) >>> 24);
	}
	
	public final float readFloat() throws IOException {
		return Float.intBitsToFloat(this.readInt());
	}
	
	public final long readLong() throws IOException {
		byte[] buffer = new byte[8];
		readFully(buffer, 0, 8);
		return (((long)buffer[7] << 56) +
                ((long)(buffer[6] & 255) << 48) +
                ((long)(buffer[5] & 255) << 40) +
                ((long)(buffer[4] & 255) << 32) +
                ((long)(buffer[3] & 255) << 24) +
                ((buffer[2] & 255) << 16) +
                ((buffer[1] & 255) <<  8) +
                ((buffer[0] & 255) <<  0));
	}

	public final double readDouble() throws IOException {
		return Double.longBitsToDouble(readLong());
	}
	
	public String readString(int length) 
		throws IOException {
		byte[] buff = new byte[length];
		readFully(buff, 0, length);
		return this.makeSafeString(buff);
	}
	
	public String readString() throws IOException {
		StringBuffer s = new StringBuffer();
		char c = 0;
		while((c = this.readUnsignedChar()) != 0)
			s.append(c);
		return s.toString();
	}
	
	public void close() {
		try {
			super.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private final String makeSafeString(final byte buffer[]) {
        final int len = buffer.length;
        for (int i = 0; i < len; i++) {
            if (buffer[i] == (byte) 0) {
                return new String(buffer, 0, i);
            }
        }
        return new String(buffer).trim();
    }

	/**
	 * 摘自java.io.DataInputStream，直接使用read容易出现缺少字节的问题
	 * @see java.io.DataInputStream.readFully(byte b[])
	 * @param b
	 * @return
	 * @throws IOException
	 */
	public final int readFully(byte b[]) throws IOException {
        return readFully(b, 0, b.length);
    }
	
	/**
	 * 摘自java.io.DataInputStream，直接使用read容易出现缺少字节的问题
	 * @see java.io.DataInputStream.readFully(byte b[])
	 * @param b
	 * @param off
	 * @param len
	 * @return
	 * @throws IOException
	 */
	public final int readFully(byte b[], int off, int len) throws IOException {
        if (len < 0)
            throw new IndexOutOfBoundsException();
        int n = 0;
        while (n < len) {
            int count = in.read(b, off + n, len - n);
            if (count < 0)
                throw new EOFException();
            n += count;
        }
        return n;
    }
	
	public int size() {
		return size;
	}
	
}
